home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Alles Voor Internet / Tout Pour Internet
/
alles voor internet.iso
/
MacInternet™
/
Archive-tools
/
UnZip MAC 5.0p1 ƒ
/
Source
/
file_io.c
< prev
next >
Wrap
Text File
|
1993-01-23
|
34KB
|
1,166 lines
/*---------------------------------------------------------------------------
file_io.c
This file contains routines for doing direct input/output, file-related
sorts of things. Most of the system-specific code for unzip is contained
here, including the non-echoing password code for decryption (bottom).
---------------------------------------------------------------------------*/
#if (!defined(__GO32__) && !defined(NeXT))
# define const
#endif
#define FILE_IO_C
#include "unzip.h"
#ifdef MSWIN
# include "wizunzip.h"
#endif
/************************************/
/* File_IO Local Prototypes, etc. */
/************************************/
#if (!defined(DOS_OS2) || defined(MSWIN))
static int dos2unix __((unsigned char *buf, int len));
int CR_flag = 0; /* when last char of buffer == CR (for dos2unix()) */
#endif
#ifdef OS2
extern int longname; /* set in mapname.c */
extern char longfilename[];
#endif
#ifdef CRYPT
# if (defined(DOS_OS2) || defined(VMS))
# define MSVMS
# ifdef DOS_OS2
# ifdef __EMX__
# define getch() _read_kbd(0, 1, 0)
# else
# ifdef __GO32__
# include <pc.h>
# define getch() getkey()
# else /* !__GO32__ */
# include <conio.h>
# endif /* ?__GO32__ */
# endif
# else /* !DOS_OS2 */
# define getch() getc(stderr)
# define OFF 0 /* for echo control */
# define ON 1
# define echoff(f) echo(OFF)
# define echon() echo(ON)
# include <descrip.h>
# include <iodef.h>
# include <ttdef.h>
# if !defined(SS$_NORMAL)
# define SS$_NORMAL 1 /* only thing we need from <ssdef.h> */
# endif
# endif /* ?DOS_OS2 */
# else /* !(DOS_OS2 || VMS) */
# ifdef TERMIO /* Amdahl, Cray, all SysV? */
# ifdef CONVEX
# include <sys/termios.h>
# include <sgtty.h>
# else /* !CONVEX */
# ifdef LINUX
# include <termios.h>
# else /* !LINUX */
# include <sys/termio.h>
# endif /* ?LINUX */
# define sgttyb termio
# define sg_flags c_lflag
# endif /* ?CONVEX */
int ioctl OF((int, int, voidp *));
# define GTTY(f,s) ioctl(f,TCGETA,(voidp *)s)
# define STTY(f,s) ioctl(f,TCSETAW,(voidp *)s)
# else /* !TERMIO */
# if (!defined(MINIX) && !defined(__386BSD__))
# include <sys/ioctl.h>
# endif /* !MINIX && !__386BSD__ */
# include <sgtty.h>
# ifdef __386BSD__
# define GTTY(f, s) ioctl(f, TIOCGETP, (voidp *) s)
# define STTY(f, s) ioctl(f, TIOCSETP, (voidp *) s)
# else /* !__386BSD__ */
# define GTTY gtty
# define STTY stty
int gtty OF((int, struct sgttyb *));
int stty OF((int, struct sgttyb *));
# endif /* ?__386BSD__ */
# endif /* ?TERMIO */
int isatty OF((int));
char *ttyname OF((int));
# if (defined(PROTO) && !defined(__GNUC__) && !defined(_AIX))
int open (char *, int, ...);
# endif
int close OF((int));
int read OF((int, voidp *, int));
# endif /* ?(DOS_OS2 || VMS) */
#endif /* CRYPT */
/******************************/
/* Function open_input_file() */
/******************************/
int open_input_file() /* return non-zero if open failed */
{
/*
* open the zipfile for reading and in BINARY mode to prevent cr/lf
* translation, which would corrupt the bitstreams
*/
#ifdef VMS
zipfd = open(zipfn, O_RDONLY, 0, "ctx=stm");
#else /* !VMS */
#ifdef UNIX
zipfd = open(zipfn, O_RDONLY);
#else /* !UNIX */
#ifdef MACOS
zipfd = open(zipfn, 0);
#else /* !MACOS */
zipfd = open(zipfn, O_RDONLY | O_BINARY);
#endif /* ?MACOS */
#endif /* ?UNIX */
#endif /* ?VMS */
if (zipfd < 1) {
fprintf(stderr, "error: can't open zipfile [ %s ]\n", zipfn);
return (1);
}
return 0;
}
/**********************/
/* Function readbuf() */
/**********************/
int readbuf(buf, size)
char *buf;
register unsigned size;
{ /* return number of bytes read into buf */
register int count;
int n;
n = size;
while (size) {
if (incnt == 0) {
if ((incnt = read(zipfd, (char *)inbuf, INBUFSIZ)) <= 0)
return (n-size);
/* buffer ALWAYS starts on a block boundary: */
cur_zipfile_bufstart += INBUFSIZ;
inptr = inbuf;
}
count = MIN(size, (unsigned)incnt);
memcpy(buf, inptr, count);
buf += count;
inptr += count;
incnt -= count;
size -= count;
}
return (n);
}
#ifndef VMS /* for VMS use code in vms.c (old VMS code below is retained
* in case of problems...will be removed in a later release) */
/*********************************/
/* Function create_output_file() */
/*********************************/
int create_output_file() /* return non-0 if creat failed */
{
/*---------------------------------------------------------------------------
Create the output file with appropriate permissions. If we've gotten to
this point and the file still exists, we have permission to blow it away.
---------------------------------------------------------------------------*/
#if (!defined(DOS_OS2) || defined(MSWIN))
CR_flag = 0; /* hack to get CR at end of buffer working */
#endif
#if (defined(UNIX) && !defined(AMIGA))
{
int mask;
#ifndef VMS
if (!stat(filename, &statbuf) && (unlink(filename) < 0)) {
fprintf(stderr, "\n%s: cannot delete old copy\n", filename);
return 1;
}
# define EXTRA_ARGS
#else /* VMS */
# define EXTRA_ARGS ,"rfm=stmlf","rat=cr"
#endif /* ?VMS */
mask = umask(0); /* now know that we own it */
outfd = creat(filename, 0xffff & pInfo->unix_attr EXTRA_ARGS);
umask(mask); /* VMS, Unix */
}
#else /* !UNIX || AMIGA */ /* file permissions set after file closed */
#ifndef MACOS
outfd = creat(filename, S_IWRITE | S_IREAD); /* DOS, OS2, Mac, Amiga */
#else /* MACOS */
{
short fDataFork=TRUE;
MACINFO mi;
OSErr err;
fMacZipped = FALSE;
CtoPstr(filename);
if (extra_field &&
(lrec.extra_field_length > sizeof(MACINFOMIN)) &&
(lrec.extra_field_length <= sizeof(MACINFO))) {
BlockMove(extra_field, &mi, lrec.extra_field_length);
if ((makeword((byte *)&mi.header) == 1992) &&
(makeword((byte *)&mi.data) ==
lrec.extra_field_length-sizeof(ZIP_EXTRA_HEADER)) &&
(mi.signature == 'JLEE')) {
gostCreator = mi.finfo.fdCreator;
gostType = mi.finfo.fdType;
fDataFork = (mi.flags & 1) ? TRUE : FALSE;
fMacZipped = true;
/* If it was Zipped w/Mac version, the filename has either */
/* a 'd' or 'r' appended. Remove the d/r when unzipping */
filename[0]-=1;
}
}
if (!fMacZipped) {
if (!aflag)
gostType = gostCreator = '\?\?\?\?';
else {
#ifdef THINK_C
gostCreator = 'KAHL';
#else
#ifdef MCH_MACINTOSH
gostCreator = 'Manx';
#else
gostCreator = 'MPS ';
#endif
#endif
gostType = 'TEXT';
}
}
PtoCstr(filename);
outfd = creat(filename, 0);
if (fMacZipped) {
CtoPstr(filename);
if (hfsflag) {
HParamBlockRec hpbr;
hpbr.fileParam.ioNamePtr = (StringPtr)filename;
hpbr.fileParam.ioVRefNum = gnVRefNum;
hpbr.fileParam.ioDirID = glDirID;
hpbr.fileParam.ioFlFndrInfo = mi.finfo;
hpbr.fileParam.ioFlCrDat = mi.lCrDat;
hpbr.fileParam.ioFlMdDat = mi.lMdDat;
err = PBHSetFInfo(&hpbr, 0);
} else {
err = SetFInfo((StringPtr)filename , 0, &mi.finfo);
}
PtoCstr(filename);
}
if (outfd != -1)
outfd = open(filename, (fDataFork)? 1 : 2);
}
#endif /* ?MACOS */
#endif /* ?(UNIX && !AMIGA) */
if (outfd < 1) {
fprintf(stderr, "\n%s: cannot create\n", filename);
return 1;
}
/*---------------------------------------------------------------------------
If newly created file is in text mode and should be binary (to disable
automatic CR/LF translations), either close it and reopen as binary or
else change the mode to binary (DOS, OS/2).
---------------------------------------------------------------------------*/
#if (!defined(UNIX) && !defined(MACOS))
if (!aflag) {
#ifdef DOS_OS2
if (setmode(outfd, O_BINARY) == -1) {
#else /* !DOS_OS2 */
close(outfd);
if ((outfd = open(filename, O_RDWR | O_BINARY)) < 1) {
#endif /* ?DOS_OS2 */
fprintf(stderr, "Can't make output file binary: %s\n", filename);
return 1;
}
}
#endif /* !UNIX && !MACOS */
return 0;
}
#endif /* !VMS */
/****************************/
/* Function FillBitBuffer() */
/****************************/
int FillBitBuffer()
{
/*
* Fill bitbuf, which is 32 bits. This function is only used by the
* READBIT and PEEKBIT macros (which are used by all of the uncompression
* routines).
*/
UWORD temp;
zipeof = 1;
while (bits_left < 25 && ReadByte(&temp) == 8)
{
bitbuf |= (ULONG)temp << bits_left;
bits_left += 8;
zipeof = 0;
}
return 0;
}
/***********************/
/* Function ReadByte() */
/***********************/
int ReadByte(x)
UWORD *x;
{
/*
* read a byte; return 8 if byte available, 0 if not
*/
if (mem_mode)
return ReadMemoryByte(x);
if (csize-- <= 0)
return 0;
if (incnt == 0) {
if ((incnt = read(zipfd, (char *)inbuf, INBUFSIZ)) <= 0)
return 0;
/* buffer ALWAYS starts on a block boundary: */
cur_zipfile_bufstart += INBUFSIZ;
inptr = inbuf;
#ifdef CRYPT
if (pInfo->encrypted) {
byte *p;
int n, t;
for (n = (longint)incnt > csize + 1 ? (int)csize + 1 : incnt,
p = inptr; n--; p++)
*p = (byte) DECRYPT(*p);
}
#endif /* CRYPT */
}
*x = *inptr++;
--incnt;
return 8;
}
#ifndef VMS /* for VMS use code in vms.c */
/**************************/
/* Function FlushOutput() */
/**************************/
int FlushOutput()
{
/*
* flush contents of output buffer; return PK-type error code
*/
#if (!defined(DOS_OS2) || defined(MSWIN))
int saved_ctrlZ = FALSE;
#endif
int len;
if (mem_mode) {
int rc = FlushMemory();
outpos += outcnt;
outcnt = 0;
outptr = outbuf;
return rc;
}
if (disk_full) {
outpos += outcnt; /* fake emptied buffer */
outcnt = 0;
outptr = outbuf;
return 50; /* ignore rest of this file */
}
if (outcnt) {
UpdateCRC(outbuf, outcnt);
if (!tflag) {
#if (!defined(DOS_OS2) || defined(MSWIN))
if (aflag) {
if (outbuf[outcnt-1] == CTRLZ) {
--outcnt;
saved_ctrlZ = TRUE;
}
len = dos2unix(outbuf, outcnt);
} else
#endif /* !DOS_OS2 || MSWIN */
len = outcnt;
#ifdef MACOS
if ((giCursor+1) >> 2 != (giCursor>>2))
SetCursor( *rghCursor[((giCursor+1)>>2)&0x03] );
giCursor = (giCursor+1) & 15;
#endif /* MACOS */
#ifdef MSWIN
/* if writing to console vs. actual file, write to Msg Window */
if (cflag)
WriteBufferToMsgWin(outout, len, FALSE);
else if (_lwrite(outfd, outout, len) != (UINT)len)
#else /* !MSWIN */
if (write(outfd, (char *)outout, len) != len)
#endif /* ?MSWIN */
#ifdef DOS_OS2
if (!cflag) /* ^Z treated as EOF, removed with -c */
#else /* !DOS_OS2 */
#ifdef MINIX
if (errno == EFBIG)
if (write(fd, outout, len/2) != len/2 ||
write(fd, outout+len/2, len/2) != len/2)
#endif /* MINIX */
#endif /* ?DOS_OS2 */
{
/* GRR: add test for force_flag when has its own switch */
fprintf(stderr,
"\n%s: write error (disk full?). Continue? (y/n/^C) ",
filename);
FFLUSH /* for Amiga and Mac MPW */
#ifdef MSWIN
disk_full = 2;
#else /* !MSWIN */
fgets(answerbuf, 9, stdin);
if (*answerbuf == 'y') /* stop writing to this file */
disk_full = 1; /* (outfd bad?), but new OK */
else
disk_full = 2; /* no: exit program */
#endif /* ?MSWIN */
return 50; /* 50: disk full */
}
}
outpos += outcnt;
outcnt = 0;
outptr = outbuf;
#if (!defined(DOS_OS2) || defined(MSWIN))
if (saved_ctrlZ) {
*outptr++ = CTRLZ;
++outcnt;
}
#endif /* !DOS_OS2 || MSWIN */
}
return 0; /* 0: no error */
}
#endif /* !VMS */
#if (!defined(DOS_OS2) || defined(MSWIN))
/***********************/
/* Function dos2unix() */
/***********************/
static int dos2unix(buf, len) /* GRR: rewrite for generic text conversions */
unsigned char *buf;
int len;
{
int new_len;
int i;
#ifdef MSWIN
unsigned char __far *walker;
#else /* !MSWIN */
unsigned char *walker;
#endif /* ?MSWIN */
new_len = len;
walker = outout;
#ifdef MACOS
/*
* Mac wants to strip LFs instead CRs from CRLF pairs
*/
if (CR_flag && *buf == LF) {
buf++;
new_len--;
len--;
CR_flag = buf[len] == CR;
}
else
CR_flag = buf[len - 1] == CR;
for (i = 0; i < len; i += 1) {
*walker++ = ascii_to_native(*buf);
if (*buf == LF) walker[-1] = CR;
if (*buf++ == CR && *buf == LF) {
new_len--;
buf++;
i++;
}
}
#else /* !MACOS */
if (CR_flag && *buf != LF)
*walker++ = ascii_to_native(CR);
CR_flag = buf[len - 1] == CR;
for (i = 0; i < len; i += 1) {
*walker++ = ascii_to_native(*buf);
if (*buf++ == CR && *buf == LF) {
new_len--;
walker[-1] = ascii_to_native(*buf++);
i++;
}
}
/*
* If the last character is a CR, then "ignore it" for now...
*/
if (walker[-1] == ascii_to_native(CR))
new_len--;
#endif /* ?MACOS */
return new_len;
}
#endif /* !DOS_OS2 || MSWIN */
#ifdef __GO32__
void _dos_setftime(int fd, UWORD dosdate, UWORD dostime)
{
asm("pushl %ebx");
asm("movl %0, %%ebx": : "g" (fd));
asm("movl %0, %%ecx": : "g" (dostime));
asm("movl %0, %%edx": : "g" (dosdate));
asm("movl $0x5701, %eax");
asm("int $0x21");
asm("popl %ebx");
}
void _dos_setfileattr(char *name, int attr)
{
asm("movl %0, %%edx": : "g" (name));
asm("movl %0, %%ecx": : "g" (attr));
asm("movl $0x4301, %eax");
asm("int $0x21");
}
#endif /* __GO32__ */
#ifdef DOS_OS2
/**************************************/
/* Function set_file_time_and_close() */
/**************************************/
void set_file_time_and_close()
/*
* MS-DOS AND OS/2 VERSION (Mac, Unix/VMS versions are below)
*
* Set the output file date/time stamp according to information from the
* zipfile directory record for this member, then close the file and set
* its permissions (archive, hidden, read-only, system). Aside from closing
* the file, this routine is optional (but most compilers support it).
*/
{
/*---------------------------------------------------------------------------
Allocate local variables needed by OS/2 and Turbo C.
---------------------------------------------------------------------------*/
#ifdef __TURBOC__
union {
struct ftime ft; /* system file time record */
struct {
UWORD ztime; /* date and time words */
UWORD zdate; /* .. same format as in .ZIP file */
} zt;
} td;
#endif /* __TURBOC__ */
/*---------------------------------------------------------------------------
Do not attempt to set the time stamp on standard output.
---------------------------------------------------------------------------*/
if (cflag) {
close(outfd);
return;
}
/*---------------------------------------------------------------------------
Copy and/or convert time and date variables, if necessary; then set the
file time/date.
---------------------------------------------------------------------------*/
#ifndef OS2
#ifdef __TURBOC__
td.zt.ztime = lrec.last_mod_file_time;
td.zt.zdate = lrec.last_mod_file_date;
setftime(outfd, &td.ft);
#else /* !__TURBOC__ */
#ifdef WIN32
{
FILETIME ft; /* 64-bit value made up of two 32 bit [low & high] */
WORD wDOSDate; /* for vconvertin from DOS date to Windows NT */
WORD wDOSTime;
HANDLE hFile; /* file handle (defined in Windows NT) */
wDOSTime = (WORD) lrec.last_mod_file_time;
wDOSDate = (WORD) lrec.last_mod_file_date;
/* The DosDateTimeToFileTime() function converts a DOS date/time
* into a 64 bit Windows NT file time */
DosDateTimeToFileTime(wDOSDate, wDOSTime, &ft);
/* Close the file and then re-open it using the Win32
* CreateFile call, so that the file can be created
* with GENERIC_WRITE access, otherwise the SetFileTime
* call will fail. */
close(outfd);
hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (!SetFileTime(hFile, NULL, NULL, &ft))
printf("\nSetFileTime failed: %d\n", GetLastError());
CloseHandle(hFile);
return;
}
#else /* !WIN32 */
_dos_setftime(outfd, lrec.last_mod_file_date, lrec.last_mod_file_time);
#endif /* ?WIN32 */
#endif /* ?__TURBOC__ */
#endif /* ?OS2 */
/*---------------------------------------------------------------------------
And finally we can close the file...at least everybody agrees on how to
do *this*. I think... Oh yeah, also change the mode according to the
stored file attributes, since we didn't do that when we opened the dude.
---------------------------------------------------------------------------*/
close(outfd);
#ifdef OS2
SetPathInfo(filename, lrec.last_mod_file_date,
lrec.last_mod_file_time, pInfo->dos_attr);
if (extra_field)
SetEAs(filename, extra_field);
if (longname)
SetLongNameEA(filename, longfilename);
#else /* !OS2 */
#ifdef __TURBOC__
if (_chmod(filename, 1, pInfo->dos_attr) != pInfo->dos_attr)
fprintf(stderr, "\nwarning: file attributes may not be correct\n");
#else /* !__TURBOC__ */
#ifdef WIN32
/* Attempt to set the file attributes. SetFileAttributes returns
* FALSE (0) if unsucessful, in which case print an error message,
* with error value returned from GetLastError call. */
pInfo->dos_attr = pInfo->dos_attr & 0x7F;
if (!(SetFileAttributes(filename, pInfo->dos_attr)))
fprintf(stderr, "\nwarning (%d): could not set file attributes\n",
GetLastError());
#else /* !WIN32 */
_dos_setfileattr(filename, pInfo->dos_attr);
#endif /* ?WIN32 */
#endif /* ?__TURBOC__ */
#endif /* ?OS2 */
} /* end function set_file_time_and_close() (DOS, OS/2) */
#else /* !DOS_OS2 */
#ifdef MACOS /* Mac */
/**************************************/
/* Function set_file_time_and_close() */
/**************************************/
void set_file_time_and_close()
/*
* MAC VERSION
*/
{
long m_time;
DateTimeRec dtr;
ParamBlockRec pbr;
HParamBlockRec hpbr;
OSErr err;
if (outfd != 1) {
close(outfd);
/*
* Macintosh bases all file modification times on the number of seconds
* elapsed since Jan 1, 1904, 00:00:00. Therefore, to maintain
* compatibility with MS-DOS archives, which date from Jan 1, 1980,
* with NO relation to GMT, the following conversions must be made:
* the Year (yr) must be incremented by 1980;
* and converted to seconds using the Mac routine Date2Secs(),
* almost similar in complexity to the Unix version :-)
* J. Lee
*/
dtr.year = (((lrec.last_mod_file_date >> 9) & 0x7f) + 1980);
dtr.month = ((lrec.last_mod_file_date >> 5) & 0x0f);
dtr.day = (lrec.last_mod_file_date & 0x1f);
dtr.hour = ((lrec.last_mod_file_time >> 11) & 0x1f);
dtr.minute = ((lrec.last_mod_file_time >> 5) & 0x3f);
dtr.second = ((lrec.last_mod_file_time & 0x1f) * 2);
Date2Secs(&dtr, (unsigned long *)&m_time);
CtoPstr(filename);
if (hfsflag) {
hpbr.fileParam.ioNamePtr = (StringPtr)filename;
hpbr.fileParam.ioVRefNum = gnVRefNum;
hpbr.fileParam.ioDirID = glDirID;
hpbr.fileParam.ioFDirIndex = 0;
err = PBHGetFInfo(&hpbr, 0L);
hpbr.fileParam.ioFlMdDat = m_time;
if ( !fMacZipped )
hpbr.fileParam.ioFlCrDat = m_time;
hpbr.fileParam.ioDirID = glDirID;
if (err == noErr)
err = PBHSetFInfo(&hpbr, 0L);
if (err != noErr)
printf("error: can't set the time for %s\n", filename);
} else {
pbr.fileParam.ioNamePtr = (StringPtr)filename;
pbr.fileParam.ioVRefNum = pbr.fileParam.ioFVersNum =
pbr.fileParam.ioFDirIndex = 0;
err = PBGetFInfo(&pbr, 0L);
pbr.fileParam.ioFlMdDat = pbr.fileParam.ioFlCrDat = m_time;
if (err == noErr)
err = PBSetFInfo(&pbr, 0L);
if (err != noErr)
printf("error: can't set the time for %s\n", filename);
}
/* set read-only perms if needed */
if ((err == noErr) && !(pInfo->unix_attr & S_IWRITE)) {
if (hfsflag) {
hpbr.fileParam.ioNamePtr = (StringPtr)filename;
hpbr.fileParam.ioVRefNum = gnVRefNum;
hpbr.fileParam.ioDirID = glDirID;
err = PBHSetFLock(&hpbr, 0);
} else
err = SetFLock((ConstStr255Param)filename, 0);
}
PtoCstr(filename);
}
}
#else /* !MACOS... */
#if (!defined(MTS) && !defined(VMS)) /* && !MTS (can't do) && !VMS: only one
* left is UNIX (for VMS use code in vms.c) */
/**************************************/
/* Function set_file_time_and_close() */
/**************************************/
void set_file_time_and_close()
/*
* UNIX VERSION (MS-DOS & OS/2, Mac versions are above)
*/
{
static short yday[]={0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
long m_time;
int yr, mo, dy, hh, mm, ss, leap, days=0;
struct utimbuf {
time_t actime; /* new access time */
time_t modtime; /* new modification time */
} tp;
#ifdef AMIGA
# define YRBASE 1978 /* in AmigaDos, counting begins 01-Jan-1978 */
struct DateStamp myadate;
/* extern char *_TZ; no longer used? */
#else /* !AMIGA */
# define YRBASE 1970
#ifdef BSD
#ifndef __386BSD__
static struct timeb tbp;
#endif /* !__386BSD__ */
#else /* !BSD */
extern long timezone;
#endif /* ?BSD */
#endif /* ?AMIGA */
/*
* Close the file *before* setting its time under Unix and AmigaDos.
*/
#ifdef AMIGA
if (cflag) /* can't set time on stdout */
return;
close(outfd);
#else /* !AMIGA */
close(outfd);
if (cflag) /* can't set time on stdout */
return;
#endif /* ?AMIGA */
/*
* These date conversions look a little weird, so I'll explain.
* UNIX bases all file modification times on the number of seconds
* elapsed since Jan 1, 1970, 00:00:00 GMT. Therefore, to maintain
* compatibility with MS-DOS archives, which date from Jan 1, 1980,
* with NO relation to GMT, the following conversions must be made:
* the Year (yr) must be incremented by 10;
* the Date (dy) must be decremented by 1;
* and the whole mess must be adjusted by TWO factors:
* relationship to GMT (ie.,Pacific Time adds 8 hrs.),
* and whether or not it is Daylight Savings Time.
* Also, the usual conversions must take place to account for leap years,
* etc.
* C. Seaman
*/
/* dissect date */
yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + (1980 - YRBASE);
mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
dy = (lrec.last_mod_file_date & 0x1f) - 1;
/* dissect time */
hh = (lrec.last_mod_file_time >> 11) & 0x1f;
mm = (lrec.last_mod_file_time >> 5) & 0x3f;
ss = (lrec.last_mod_file_time & 0x1f) * 2;
/* leap = # of leap years from BASE up to but not including current year */
leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */
/* How many days from BASE to this year? (& add expired days this year) */
days = (yr * 365) + (leap - 492) + yday[mo];
/* if year is a leap year and month is after February, add another day */
if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
++days; /* OK through 2199 */
#ifdef AMIGA
/* _TZ = getenv("TZ"); does Amiga not have TZ and tzset() after all? */
myadate.ds_Days = days+dy-2; /* off by one? */
myadate.ds_Minute = hh*60+mm;
myadate.ds_Tick = ss*TICKS_PER_SECOND;
if (!(SetFileDate(filename, &myadate)))
fprintf(stderr, "error: can't set the time for %s\n", filename);
#else /* !AMIGA */
/* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
m_time = ((days + dy) * 86400) + (hh * 3600) + (mm * 60) + ss;
#ifdef BSD
#ifndef __386BSD__
ftime(&tbp);
m_time += tbp.timezone * 60L;
#endif
/* #elif WIN32
* don't do anything right now (esp. since "elif" is not legal for old cc's */
#else /* !BSD */
tzset(); /* set `timezone' */
m_time += timezone; /* account for timezone differences */
#endif /* ?BSD */
#ifdef __386BSD__
m_time += localtime(&m_time)->tm_gmtoff;
#else
if (localtime(&m_time)->tm_isdst)
m_time -= 60L * 60L; /* adjust for daylight savings time */
#endif
tp.actime = m_time; /* set access time */
tp.modtime = m_time; /* set modification time */
/* set the time stamp on the file */
if (utime(filename, &tp))
fprintf(stderr, "error: can't set the time for %s\n", filename);
#endif /* ?AMIGA */
}
#endif /* !MTS && !VMS */
#endif /* ?MACOS */
#endif /* ?DOS_OS2 */
/************************/
/* Function handler() */
/************************/
void handler(signal) /* upon interrupt, turn on echo and exit cleanly */
int signal;
{
#if (defined(SIGBUS) || defined(SIGSEGV))
static char *corrupt = "error: zipfile probably corrupt\n";
#endif
#ifndef DOS_OS2
#ifdef CRYPT
echon();
#endif /* CRYPT */
putc('\n', stderr);
#endif /* !DOS_OS2 */
#ifdef SIGBUS
if (signal == SIGBUS) {
fprintf(stderr, corrupt);
exit(3);
}
#endif /* SIGBUS */
#ifdef SIGSEGV
if (signal == SIGSEGV) {
fprintf(stderr, corrupt);
exit(3);
}
#endif /* SIGSEGV */
exit(0);
}
/*******************************/
/* Non-echoing password code */
/*******************************/
#ifdef CRYPT
#ifndef DOS_OS2
#ifdef VMS
int echo(opt)
int opt;
{
/*---------------------------------------------------------------------------
Based on VMSmunch.c, which in turn was based on Joe Meadows' file.c code.
---------------------------------------------------------------------------
* For VMS v5.x:
* IO$_SENSEMODE/SETMODE info: Programming, Vol. 7A, System Programming,
* I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
* sys$assign(), sys$qio() info: Programming, Vol. 4B, System Services,
* System Services Reference Manual, pp. sys-23, sys-379
* fixed-length descriptor info: Programming, Vol. 3, System Services,
* Intro to System Routines, sec. 2.9.2
* GRR, 15 Aug 91
---------------------------------------------------------------------------*/
static struct dsc$descriptor_s DevDesc =
{9, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$INPUT"};
/* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
static short DevChan, iosb[4];
static long i, status;
static unsigned long oldmode[2], newmode[2]; /* each = 8 bytes */
/*---------------------------------------------------------------------------
Assign a channel to standard input.
---------------------------------------------------------------------------*/
status = sys$assign(&DevDesc, &DevChan, 0, 0);
if (!(status & 1))
return status;
/*---------------------------------------------------------------------------
Use sys$qio and the IO$_SENSEMODE function to determine the current tty
status (for password reading, could use IO$_READVBLK function instead,
but echo on/off will be more general).
---------------------------------------------------------------------------*/
status = sys$qio(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
oldmode, 8, 0, 0, 0, 0);
if (!(status & 1))
return status;
status = iosb[0];
if (!(status & 1))
return status;
/*---------------------------------------------------------------------------
Copy old mode into new-mode buffer, then modify to be either NOECHO or
ECHO (depending on function argument opt).
---------------------------------------------------------------------------*/
newmode[0] = oldmode[0];
newmode[1] = oldmode[1];
if (opt == OFF)
newmode[1] |= TT$M_NOECHO; /* set NOECHO bit */
else
newmode[1] &= ~((unsigned long) TT$M_NOECHO); /* clear NOECHO bit */
/*---------------------------------------------------------------------------
Use the IO$_SETMODE function to change the tty status.
---------------------------------------------------------------------------*/
status = sys$qio(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
newmode, 8, 0, 0, 0, 0);
if (!(status & 1))
return status;
status = iosb[0];
if (!(status & 1))
return status;
/*---------------------------------------------------------------------------
Deassign the sys$input channel by way of clean-up, then exit happily.
---------------------------------------------------------------------------*/
status = sys$dassgn(DevChan);
if (!(status & 1))
return status;
return SS$_NORMAL; /* we be happy */
} /* end function echo() */
#else /* !VMS */
static int echofd=(-1); /* file descriptor whose echo is off */
void echoff(f)
int f; /* file descriptor for which to turn echo off */
/* Turn echo off for file descriptor f. Assumes that f is a tty device. */
{
struct sgttyb sg; /* tty device structure */
echofd = f;
GTTY(f, &sg); /* get settings */
sg.sg_flags &= ~ECHO; /* turn echo off */
STTY(f, &sg);
}
void echon()
/* Turn echo back on for file descriptor echofd. */
{
struct sgttyb sg; /* tty device structure */
if (echofd != -1) {
GTTY(echofd, &sg); /* get settings */
sg.sg_flags |= ECHO; /* turn echo on */
STTY(echofd, &sg);
echofd = -1;
}
}
#endif /* ?VMS */
#endif /* !DOS_OS2 */
char *getp(m, p, n)
char *m; /* prompt for password */
char *p; /* return value: line input */
int n; /* bytes available in p[] */
/* Get a password of length n-1 or less into *p using the prompt *m.
The entered password is not echoed. Return p on success, NULL on
failure (can't get controlling tty). */
{
char c; /* one-byte buffer for read() to use */
int i; /* number of characters input */
char *w; /* warning on retry */
#ifndef DOS_OS2
#ifndef VMS
int f; /* file decsriptor for tty device */
/* turn off echo on tty */
if (!isatty(2))
return NULL; /* error if not tty */
if ((f = open(ttyname(2), 0, 0)) == -1)
return NULL;
#endif /* !VMS */
echoff(f); /* turn echo off */
#endif /* !DOS_OS2 */
/* get password */
w = "";
do {
#ifdef VMS /* bug: VMS adds '\n' to NULL fputs (apparently) */
if (*w)
#endif /* VMS */
fputs(w, stderr); /* warning if back again */
fputs(m, stderr); /* prompt */
fflush(stderr);
i = 0;
do { /* read line, keeping n */
#ifdef MSVMS
if ((c = (char)getch()) == '\r')
c = '\n';
#else /* !MSVMS */
read(f, &c, 1);
#endif /* ?MSVMS */
if (i < n)
p[i++] = c;
} while (c != '\n');
putc('\n', stderr); fflush(stderr);
w = "(line too long--try again)\n";
} while (p[i-1] != '\n');
p[i-1] = 0; /* terminate at newline */
#ifndef DOS_OS2
echon(); /* turn echo back on */
#ifndef VMS
close(f);
#endif /* !VMS */
#endif /* !DOS_OS2 */
/* return pointer to password */
return p;
}
#endif /* CRYPT */